package com.wyh.service.serviceImpl.appservieripml;


import cn.hutool.json.JSONObject;
import com.wyh.common.utils.WXShareUtils;
import com.wyh.common.utils.WeixinUtils;
import com.wyh.common.utils.WxShareConfigUtils;
import com.wyh.domain.dto.groupfour.myproprietorDTO.ShareInfoDTO;
import com.wyh.domain.vo.gruopfour.myProprietorVO.ShareInfoVO;
import com.wyh.service.appservice.WXShareService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * Created by xxs on 2021/11/18 20:17
 *
 * @Description
 */
@Service
public class WXShareServiceImpl implements WXShareService {


    private static final Logger logger = LoggerFactory.getLogger(WXShareServiceImpl.class);

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String ACCESS_TOKEN = "ACCESS_TOKEN";

    private static final String JS_API_TICKET = "JS_API_TICKET";

    @Override
    public ShareInfoVO getWxConfig(ShareInfoDTO shareInfoDTO) {
        ShareInfoVO shareInfoVO = new ShareInfoVO();

        String timestamp = getTimestamp(); // 必填，生成签名的时间戳
        String nonceStr = getNonceStr(); // 必填，生成签名的随机串

        //获取jsapi_ticket
        String jsApiTicket = getJsApiTicket();

        //生成JS-SDK权限验证的签名
        String signature = "";
        //注意这里参数名必须全部小写，且必须有序
        String sign = "jsapi_ticket=" + jsApiTicket
                +"&noncestr=" + nonceStr
                + "&timestamp=" + timestamp
                +"&url=" + shareInfoDTO.getUrl();
        try{
            //进行sha1签名
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(sign.getBytes("UTF-8"));
            signature = WXShareUtils.byteToHex(crypt.digest());
        }catch (NoSuchAlgorithmException | UnsupportedEncodingException e){
            e.printStackTrace();
        }
        shareInfoVO.setAppId(WxShareConfigUtils.appid);
        shareInfoVO.setTimeStamp(timestamp);
        shareInfoVO.setNonceStr(nonceStr);
        shareInfoVO.setSign(signature);
        return shareInfoVO;
    }


    /**
     * @param
     * @Description:  获取token
     */
    private String getAccessToken() {
        String accessToken = redisTemplate.opsForValue().get(ACCESS_TOKEN);
        if (!StringUtils.isNotBlank(accessToken)){
            //缓存无，重新获取token
            String url = WxShareConfigUtils.getTokenUrl
                    + "grant_type=client_credential&appid=" + WxShareConfigUtils.appid + "&secret=" + WxShareConfigUtils.appsecret;
            JSONObject json = WeixinUtils.doGet(url);
            if (json != null) {
                accessToken = json.getStr("access_token");
                Integer time = Integer.parseInt(json.getStr("expires_in"));
                //减去一个小时以提前刷新避免过期
                redisTemplate.opsForValue().set(ACCESS_TOKEN,accessToken,time - 3600);
            }
        }
        logger.info("getAccessToken access_token: {}", accessToken);
        return accessToken.trim();
    }


    /**
     * @param
     * @Description:  获取ticket
     */
    private String getJsApiTicket() {
        String jsApiTicket = redisTemplate.opsForValue().get(JS_API_TICKET);
        if (!StringUtils.isNotBlank(jsApiTicket)){
            //获取全局的access_token，唯一票据
            String accessToken = getAccessToken();
            if (StringUtils.isNotBlank(accessToken)) {
                //获取jsapi_ticket
                String url = WxShareConfigUtils.getTicketUrl+"access_token="+accessToken+"&type=jsapi";
                JSONObject json = WeixinUtils.doGet(url);
                if (json != null) {
                    jsApiTicket = json.getStr("ticket");
                    Integer time = Integer.parseInt(json.getStr("expires_in"));
                    redisTemplate.opsForValue().set(JS_API_TICKET,jsApiTicket,time - 3600);
                }
            }
        }
        logger.info("getJsApiTicket jsApiTicket: {}", jsApiTicket);
        return jsApiTicket.trim();
    }


    /**
     * @param
     * @Description:  获取随机字符串
     */
    private static String getNonceStr() {
        return UUID.randomUUID().toString().replace("-", "");
    }


    /**
     * @param
     * @Description:  获取时间戳
     */
    private static String getTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

}
